home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 2 / AACD 2.iso / AACD / Magazine / GraphicsCards / StormMesa / 3Dfx / demos / fire.c < prev    next >
C/C++ Source or Header  |  1998-12-15  |  14KB  |  701 lines

  1. /*
  2.  * This program is under the GNU GPL.
  3.  * Use at your own risk.
  4.  *
  5.  * written by David Bucciarelli (tech.hmw@plus.it)
  6.  *            Humanware s.r.l.
  7.  */
  8.  
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <math.h>
  12. #include <time.h>
  13. #include <GL/glut.h>
  14. #include "image.h"
  15.  
  16. #ifdef WIN32
  17. #include <windows.h>
  18. #include <mmsystem.h>
  19. #endif
  20.  
  21. #ifdef XMESA
  22. #include "GL/xmesa.h"
  23. static int fullscreen=1;
  24. #endif
  25.  
  26. #ifndef M_PI
  27. #define M_PI 3.1415926535
  28. #endif
  29.  
  30. #define vinit(a,i,j,k) {\
  31.   (a)[0]=i;\
  32.   (a)[1]=j;\
  33.   (a)[2]=k;\
  34. }
  35.  
  36. #define vinit4(a,i,j,k,w) {\
  37.   (a)[0]=i;\
  38.   (a)[1]=j;\
  39.   (a)[2]=k;\
  40.   (a)[3]=w;\
  41. }
  42.  
  43.  
  44. #define vadds(a,dt,b) {\
  45.   (a)[0]+=(dt)*(b)[0];\
  46.   (a)[1]+=(dt)*(b)[1];\
  47.   (a)[2]+=(dt)*(b)[2];\
  48. }
  49.  
  50. #define vequ(a,b) {\
  51.   (a)[0]=(b)[0];\
  52.   (a)[1]=(b)[1];\
  53.   (a)[2]=(b)[2];\
  54. }
  55.  
  56. #define vinter(a,dt,b,c) {\
  57.   (a)[0]=(dt)*(b)[0]+(1.0-dt)*(c)[0];\
  58.   (a)[1]=(dt)*(b)[1]+(1.0-dt)*(c)[1];\
  59.   (a)[2]=(dt)*(b)[2]+(1.0-dt)*(c)[2];\
  60. }
  61.  
  62. #define clamp(a)        ((a) < 0.0 ? 0.0 : ((a) < 1.0 ? (a) : 1.0))
  63.  
  64. #define vclamp(v) {\
  65.   (v)[0]=clamp((v)[0]);\
  66.   (v)[1]=clamp((v)[1]);\
  67.   (v)[2]=clamp((v)[2]);\
  68. }
  69.  
  70. static int WIDTH=640;
  71. static int HEIGHT=480;
  72.  
  73. #define FRAME 50
  74. #define DIMP 20.0
  75. #define DIMTP 16.0
  76.  
  77. #define RIDCOL 0.4
  78.  
  79. #define NUMTREE 50
  80. #define TREEINR 2.5
  81. #define TREEOUTR 8.0
  82.  
  83. #define AGRAV -9.8
  84.  
  85. typedef struct {
  86.   int age;
  87.   float p[3][3];
  88.   float v[3];
  89.   float c[3][4];
  90. } part;
  91.  
  92. static float treepos[NUMTREE][3];
  93.  
  94. static float black[3]={0.0,0.0,0.0};
  95. static float blu[3]={0.0,0.2,1.0};
  96. static float blu2[3]={0.0,1.0,1.0};
  97.  
  98. static float fogcolor[4]={1.0,1.0,1.0,1.0};
  99.  
  100. static float q[4][3]={
  101.   {-DIMP,0.0,-DIMP},
  102.   {DIMP,0.0,-DIMP},
  103.   {DIMP,0.0,DIMP},
  104.   {-DIMP,0.0,DIMP}
  105. };
  106.  
  107. static float qt[4][2]={
  108.   {-DIMTP,-DIMTP},
  109.   {DIMTP,-DIMTP},
  110.   {DIMTP,DIMTP},
  111.   {-DIMTP,DIMTP}
  112. };
  113.  
  114. static int win=0;
  115.  
  116. static int np;
  117. static float eject_r,dt,maxage,eject_vy,eject_vl;
  118. static short shadows;
  119. static float ridtri;
  120. static int fog=1;
  121. static int help=1;
  122. static int joyavailable=0;
  123. static int joyactive=0;
  124.  
  125. static part *p;
  126.  
  127. static int groundid;
  128. static int treeid;
  129.  
  130. static float obs[3]={2.0,1.0,0.0};
  131. static float dir[3];
  132. static float v=0.0;
  133. static float alpha=-90.0;
  134. static float beta=90.0;
  135.  
  136. static float gettime(void)
  137. {
  138.   static clock_t told=0;
  139.   clock_t tnew,ris;
  140.  
  141.   tnew=clock();
  142.  
  143.   ris=tnew-told;
  144.  
  145.   told=tnew;
  146.  
  147.   return(ris/(float)CLOCKS_PER_SEC);
  148. }
  149.  
  150. float vrnd(void)
  151. {
  152.   return(((float)rand())/RAND_MAX);
  153. }
  154.  
  155. static void setnewpart(part *p)
  156. {
  157.   float a,v[3],*c;
  158.  
  159.   p->age=0;
  160.  
  161.   a=vrnd()*3.14159265359*2.0;
  162.  
  163.   vinit(v,sin(a)*eject_r*vrnd(),0.15,cos(a)*eject_r*vrnd());
  164.   vinit(p->p[0],v[0]+vrnd()*ridtri,v[1]+vrnd()*ridtri,v[2]+vrnd()*ridtri);
  165.   vinit(p->p[1],v[0]+vrnd()*ridtri,v[1]+vrnd()*ridtri,v[2]+vrnd()*ridtri);
  166.   vinit(p->p[2],v[0]+vrnd()*ridtri,v[1]+vrnd()*ridtri,v[2]+vrnd()*ridtri);
  167.  
  168.   vinit(p->v,v[0]*eject_vl/(eject_r/2),vrnd()*eject_vy+eject_vy/2,v[2]*eject_vl/(eject_r/2));
  169.  
  170.   c=blu;
  171.  
  172.   vinit4(p->c[0],c[0]*((1.0-RIDCOL)+vrnd()*RIDCOL),
  173.      c[1]*((1.0-RIDCOL)+vrnd()*RIDCOL),
  174.      c[2]*((1.0-RIDCOL)+vrnd()*RIDCOL),
  175.      1.0);
  176.   vinit4(p->c[1],c[0]*((1.0-RIDCOL)+vrnd()*RIDCOL),
  177.      c[1]*((1.0-RIDCOL)+vrnd()*RIDCOL),
  178.      c[2]*((1.0-RIDCOL)+vrnd()*RIDCOL),
  179.      1.0);
  180.   vinit4(p->c[2],c[0]*((1.0-RIDCOL)+vrnd()*RIDCOL),
  181.      c[1]*((1.0-RIDCOL)+vrnd()*RIDCOL),
  182.      c[2]*((1.0-RIDCOL)+vrnd()*RIDCOL),
  183.      1.0);
  184. }
  185.  
  186. static void setpart(part *p)
  187. {
  188.   float fact;
  189.  
  190.   if(p->p[0][1]<0.1) {
  191.     setnewpart(p);
  192.     return;
  193.   }
  194.  
  195.   p->v[1]+=AGRAV*dt;
  196.  
  197.   vadds(p->p[0],dt,p->v);
  198.   vadds(p->p[1],dt,p->v);
  199.   vadds(p->p[2],dt,p->v);
  200.  
  201.   p->age++;
  202.  
  203.   if((p->age)>maxage) {
  204.     vequ(p->c[0],blu2);
  205.     vequ(p->c[1],blu2);
  206.     vequ(p->c[2],blu2);
  207.   } else {
  208.     fact=1.0/maxage;
  209.     vadds(p->c[0],fact,blu2);
  210.     vclamp(p->c[0]);
  211.     p->c[0][3]=fact*(maxage-p->age);
  212.  
  213.     vadds(p->c[1],fact,blu2);
  214.     vclamp(p->c[1]);
  215.     p->c[1][3]=fact*(maxage-p->age);
  216.  
  217.     vadds(p->c[2],fact,blu2);
  218.     vclamp(p->c[2]);
  219.     p->c[2][3]=fact*(maxage-p->age);
  220.   }
  221. }
  222.  
  223. static void drawtree(float x, float y, float z)
  224. {
  225.   glBegin(GL_QUADS);
  226.   glTexCoord2f(0.0,0.0);
  227.   glVertex3f(x-1.5,y+0.0,z);
  228.  
  229.   glTexCoord2f(1.0,0.0);
  230.   glVertex3f(x+1.5,y+0.0,z);
  231.  
  232.   glTexCoord2f(1.0,1.0);
  233.   glVertex3f(x+1.5,y+3.0,z);
  234.  
  235.   glTexCoord2f(0.0,1.0);
  236.   glVertex3f(x-1.5,y+3.0,z);
  237.  
  238.  
  239.   glTexCoord2f(0.0,0.0);
  240.   glVertex3f(x,y+0.0,z-1.5);
  241.  
  242.   glTexCoord2f(1.0,0.0);
  243.   glVertex3f(x,y+0.0,z+1.5);
  244.  
  245.   glTexCoord2f(1.0,1.0);
  246.   glVertex3f(x,y+3.0,z+1.5);
  247.  
  248.   glTexCoord2f(0.0,1.0);
  249.   glVertex3f(x,y+3.0,z-1.5);
  250.  
  251.   glEnd();
  252.  
  253. }
  254.  
  255. static void calcposobs(void)
  256. {
  257.   dir[0]=sin(alpha*M_PI/180.0);
  258.   dir[2]=cos(alpha*M_PI/180.0)*sin(beta*M_PI/180.0);
  259.   dir[1]=cos(beta*M_PI/180.0);
  260.  
  261.   obs[0]+=v*dir[0];
  262.   obs[1]+=v*dir[1];
  263.   obs[2]+=v*dir[2];
  264. }
  265.  
  266. static void printstring(void *font, char *string)
  267. {
  268.   int len,i;
  269.  
  270.   len=(int)strlen(string);
  271.   for(i=0;i<len;i++)
  272.     glutBitmapCharacter(font,string[i]);
  273. }
  274.  
  275. static void reshape(int width, int height)
  276. {
  277.   WIDTH=width;
  278.   HEIGHT=height;
  279.   glViewport(0,0,(GLint)width,(GLint)height);
  280.   glMatrixMode(GL_PROJECTION);
  281.   glLoadIdentity();
  282.   gluPerspective(70.0,width/(float)height,0.1,30.0);
  283.  
  284.   glMatrixMode(GL_MODELVIEW);
  285. }
  286.  
  287. static void printhelp(void)
  288. {
  289.   glColor4f(0.0,0.0,0.0,0.5);
  290.   glRecti(40,40,600,440);
  291.  
  292.   glColor3f(1.0,0.0,0.0);
  293.   glRasterPos2i(300,420);
  294.   printstring(GLUT_BITMAP_TIMES_ROMAN_24,"Help");
  295.  
  296.   glRasterPos2i(60,390);
  297.   printstring(GLUT_BITMAP_TIMES_ROMAN_24,"h - Togle Help");
  298.  
  299.   glRasterPos2i(60,360);
  300.   printstring(GLUT_BITMAP_TIMES_ROMAN_24,"t - Increase particle size");
  301.   glRasterPos2i(60,330);
  302.   printstring(GLUT_BITMAP_TIMES_ROMAN_24,"T - Decrease particle size");
  303.  
  304.   glRasterPos2i(60,300);
  305.   printstring(GLUT_BITMAP_TIMES_ROMAN_24,"r - Increase emission radius");
  306.   glRasterPos2i(60,270);
  307.   printstring(GLUT_BITMAP_TIMES_ROMAN_24,"R - Decrease emission radius");
  308.  
  309.   glRasterPos2i(60,240);
  310.   printstring(GLUT_BITMAP_TIMES_ROMAN_24,"f - Togle Fog");
  311.   glRasterPos2i(60,210);
  312.   printstring(GLUT_BITMAP_TIMES_ROMAN_24,"s - Togle shadows");
  313.   glRasterPos2i(60,180);
  314.   printstring(GLUT_BITMAP_TIMES_ROMAN_24,"Arrow Keys - Rotate");
  315.   glRasterPos2i(60,150);
  316.   printstring(GLUT_BITMAP_TIMES_ROMAN_24,"a - Increase velocity");
  317.   glRasterPos2i(60,120);
  318.   printstring(GLUT_BITMAP_TIMES_ROMAN_24,"z - Decrease velocity");
  319.  
  320.   glRasterPos2i(60,90);
  321.   if(joyavailable)
  322.     printstring(GLUT_BITMAP_TIMES_ROMAN_24,"j - Togle jostick control (Joystick control available)");
  323.   else
  324.     printstring(GLUT_BITMAP_TIMES_ROMAN_24,"(No Joystick control available)");
  325. }
  326.  
  327. static void dojoy(void)
  328. {
  329. #ifdef WIN32
  330.   static UINT max[2]={0,0};
  331.   static UINT min[2]={0xffffffff,0xffffffff},center[2];
  332.   MMRESULT res;
  333.   JOYINFO joy;
  334.  
  335.   res=joyGetPos(JOYSTICKID1,&joy);
  336.  
  337.   if(res==JOYERR_NOERROR) {
  338.     joyavailable=1;
  339.  
  340.     if(max[0]<joy.wXpos)
  341.       max[0]=joy.wXpos;
  342.     if(min[0]>joy.wXpos)
  343.       min[0]=joy.wXpos;
  344.     center[0]=(max[0]+min[0])/2;
  345.  
  346.     if(max[1]<joy.wYpos)
  347.       max[1]=joy.wYpos;
  348.     if(min[1]>joy.wYpos)
  349.       min[1]=joy.wYpos;
  350.     center[1]=(max[1]+min[1])/2;
  351.  
  352.     if(joyactive) {
  353.       if(fabs(center[0]-(float)joy.wXpos)>0.1*(max[0]-min[0]))
  354.     alpha+=2.5*(center[0]-(float)joy.wXpos)/(max[0]-min[0]);
  355.       if(fabs(center[1]-(float)joy.wYpos)>0.1*(max[1]-min[1]))
  356.     beta+=2.5*(center[1]-(float)joy.wYpos)/(max[1]-min[1]);
  357.  
  358.       if(joy.wButtons & JOY_BUTTON1)
  359.     v+=0.01;
  360.       if(joy.wButtons & JOY_BUTTON2)
  361.     v-=0.01;
  362.     }
  363.   } else
  364.     joyavailable=0;
  365. #endif
  366. }
  367.  
  368. static void drawfire(void)
  369. {
  370.   static int count=0;
  371.   static char frbuf[80];
  372.   int    j;
  373.   float fr;
  374.  
  375.   dojoy();
  376.  
  377.   glEnable(GL_DEPTH_TEST);
  378.  
  379.   if(fog)
  380.     glEnable(GL_FOG);
  381.   else
  382.     glDisable(GL_FOG);
  383.  
  384.   glDepthMask(GL_TRUE);
  385.   glClearColor(1.0,1.0,1.0,1.0);
  386.   glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
  387.  
  388.   glPushMatrix();
  389.   calcposobs();
  390.   gluLookAt(obs[0],obs[1],obs[2],
  391.         obs[0]+dir[0],obs[1]+dir[1],obs[2]+dir[2],
  392.         0.0,1.0,0.0);
  393.  
  394.   glColor4f(1.0,1.0,1.0,1.0);
  395.  
  396.   glEnable(GL_TEXTURE_2D);
  397.  
  398.   glBindTexture(GL_TEXTURE_2D,groundid);
  399.   glBegin(GL_QUADS);
  400.   glTexCoord2fv(qt[0]);
  401.   glVertex3fv(q[0]);
  402.   glTexCoord2fv(qt[1]);
  403.   glVertex3fv(q[1]);
  404.   glTexCoord2fv(qt[2]);
  405.   glVertex3fv(q[2]);
  406.   glTexCoord2fv(qt[3]);
  407.   glVertex3fv(q[3]);
  408.   glEnd();
  409.  
  410.   glEnable(GL_ALPHA_TEST);
  411.   glAlphaFunc(GL_GEQUAL,0.9);
  412.  
  413.   glBindTexture(GL_TEXTURE_2D,treeid);
  414.   for(j=0;j<NUMTREE;j++)
  415.     drawtree(treepos[j][0],treepos[j][1],treepos[j][2]);
  416.   
  417.   glDisable(GL_TEXTURE_2D);
  418.   glDepthMask(GL_FALSE);
  419.   glDisable(GL_ALPHA_TEST);
  420.  
  421.   if(shadows) {
  422.     glBegin(GL_TRIANGLES);
  423.     for(j=0;j<np;j++) {
  424.       glColor4f(black[0],black[1],black[2],p[j].c[0][3]);
  425.       glVertex3f(p[j].p[0][0],0.1,p[j].p[0][2]);
  426.  
  427.       glColor4f(black[0],black[1],black[2],p[j].c[1][3]);
  428.       glVertex3f(p[j].p[1][0],0.1,p[j].p[1][2]);
  429.  
  430.       glColor4f(black[0],black[1],black[2],p[j].c[2][3]);
  431.       glVertex3f(p[j].p[2][0],0.1,p[j].p[2][2]);
  432.     }
  433.     glEnd();
  434.   }
  435.  
  436.   glBegin(GL_TRIANGLES);
  437.   for(j=0;j<np;j++) {
  438.     glColor4fv(p[j].c[0]);
  439.     glVertex3fv(p[j].p[0]);
  440.  
  441.     glColor4fv(p[j].c[1]);
  442.     glVertex3fv(p[j].p[1]);
  443.  
  444.     glColor4fv(p[j].c[2]);
  445.     glVertex3fv(p[j].p[2]);
  446.  
  447.     setpart(&p[j]);
  448.   }
  449.   glEnd();
  450.  
  451.   if((count % FRAME)==0) {
  452.     fr=gettime();
  453.     sprintf(frbuf,"Frame rate: %f",FRAME/fr);
  454.   }
  455.  
  456.   glDisable(GL_TEXTURE_2D);
  457.   glDisable(GL_ALPHA_TEST);
  458.   glDisable(GL_DEPTH_TEST);
  459.   glDisable(GL_FOG);
  460.  
  461.   glMatrixMode(GL_PROJECTION);
  462.   glLoadIdentity();
  463.   glOrtho(-0.5,639.5,-0.5,479.5,-1.0,1.0);
  464.   glMatrixMode(GL_MODELVIEW);
  465.   glLoadIdentity();
  466.  
  467.   glColor3f(1.0,0.0,0.0);
  468.   glRasterPos2i(10,10);
  469.   printstring(GLUT_BITMAP_HELVETICA_18,frbuf);
  470.   glRasterPos2i(370,470);
  471.   printstring(GLUT_BITMAP_HELVETICA_10,"Fire V1.5 Written by David Bucciarelli (tech.hmw@plus.it)");
  472.  
  473.   if(help)
  474.     printhelp();
  475.  
  476.   reshape(WIDTH,HEIGHT);
  477.   glPopMatrix();
  478.  
  479.   glutSwapBuffers();
  480.  
  481.   count++;
  482. }
  483.  
  484.  
  485. static void special(int key, int x, int y)
  486. {
  487.   switch (key) {
  488.   case GLUT_KEY_LEFT:
  489.     alpha+=2.0;
  490.     break;
  491.   case GLUT_KEY_RIGHT:
  492.     alpha-=2.0;
  493.     break;
  494.   case GLUT_KEY_DOWN:
  495.     beta-=2.0;
  496.     break;
  497.   case GLUT_KEY_UP:
  498.     beta+=2.0;
  499.     break;
  500.   }
  501. }
  502.  
  503. static void key(unsigned char key, int x, int y)
  504. {
  505.   switch (key) {
  506.   case 27:
  507.     exit(0);
  508.     break;
  509.  
  510.   case 'a':
  511.     v+=0.01;
  512.     break;
  513.   case 'z':
  514.     v-=0.01;
  515.     break;
  516.  
  517.   case 'j':
  518.     joyactive=(!joyactive);
  519.     break;
  520.   case 'h':
  521.     help=(!help);
  522.     break;
  523.   case 'f':
  524.     fog=(!fog);
  525.     break;
  526.   case 's':
  527.     shadows= !shadows;
  528.     break;
  529.   case 'R':
  530.     eject_r-=0.03;
  531.     break;
  532.   case 'r':
  533.     eject_r+=0.03;
  534.     break;
  535.   case 't':
  536.     ridtri+=0.005;
  537.     break;
  538.   case 'T':
  539.     ridtri-=0.005;
  540.     break;
  541. #ifdef XMESA
  542.   case ' ':
  543.     XMesaSetFXmode(fullscreen ? XMESA_FX_FULLSCREEN : XMESA_FX_WINDOW);
  544.     fullscreen=(!fullscreen);
  545.     break;
  546. #endif
  547.   }
  548. }
  549.  
  550. static void inittextures(void)
  551. {
  552.   IMAGE *img;
  553.   GLenum gluerr;
  554.   GLubyte tex[128][128][4];
  555.   int x,y;
  556.  
  557.   glGenTextures(1,&groundid);
  558.   glBindTexture(GL_TEXTURE_2D,groundid);
  559.  
  560.   if(!(img=ImageLoad("s128.rgb"))) {
  561.     fprintf(stderr,"Error reading a texture.\n");
  562.     exit(-1);
  563.   }
  564.  
  565.   glPixelStorei(GL_UNPACK_ALIGNMENT,4);
  566.   if((gluerr=gluBuild2DMipmaps(GL_TEXTURE_2D, 3, img->sizeX, img->sizeY, GL_RGB,
  567.                    GL_UNSIGNED_BYTE, (GLvoid *)(img->data)))) {
  568.     fprintf(stderr,"GLULib%s\n",gluErrorString(gluerr));
  569.     exit(-1);
  570.   }
  571.  
  572.   glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
  573.   glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
  574.  
  575.   glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR);
  576.   glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
  577.  
  578.   glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_DECAL);
  579.  
  580.   glGenTextures(1,&treeid);
  581.   glBindTexture(GL_TEXTURE_2D,treeid);
  582.  
  583.   if(!(img=ImageLoad("tree2.rgb"))) {
  584.     fprintf(stderr,"Error reading a texture.\n");
  585.     exit(-1);
  586.   }
  587.  
  588.   for(y=0;y<128;y++)
  589.     for(x=0;x<128;x++) {
  590.       tex[x][y][0]=img->data[(y+x*128)*3];
  591.       tex[x][y][1]=img->data[(y+x*128)*3+1];
  592.       tex[x][y][2]=img->data[(y+x*128)*3+2];
  593.       if((tex[x][y][0]==tex[x][y][1]) && (tex[x][y][1]==tex[x][y][2]) && (tex[x][y][2]==255))
  594.     tex[x][y][3]=0;
  595.       else
  596.     tex[x][y][3]=255;
  597.     }
  598.   
  599.   if((gluerr=gluBuild2DMipmaps(GL_TEXTURE_2D, 4, 128, 128, GL_RGBA,
  600.                    GL_UNSIGNED_BYTE, (GLvoid *)(tex)))) {
  601.     fprintf(stderr,"GLULib%s\n",gluErrorString(gluerr));
  602.     exit(-1);
  603.   }
  604.  
  605.   glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
  606.   glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
  607.  
  608.   glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR);
  609.   glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
  610.  
  611.   glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
  612. }
  613.  
  614. static void inittree(void)
  615. {
  616.   int i;
  617.   float dist;
  618.  
  619.   for(i=0;i<NUMTREE;i++)
  620.     do {
  621.       treepos[i][0]=vrnd()*TREEOUTR*2.0-TREEOUTR;
  622.       treepos[i][1]=0.0;
  623.       treepos[i][2]=vrnd()*TREEOUTR*2.0-TREEOUTR;
  624.       dist=sqrt(treepos[i][0]*treepos[i][0]+treepos[i][2]*treepos[i][2]);
  625.     } while((dist<TREEINR) || (dist>TREEOUTR));
  626. }
  627.  
  628. int main(int ac,char **av)
  629. {
  630.   int i;
  631.  
  632.   fprintf(stderr,"Fire V1.5\nWritten by David Bucciarelli (tech.hmw@plus.it)\n");
  633.  
  634.   /* Default settings */
  635.  
  636.   WIDTH=640;
  637.   HEIGHT=480;
  638.   np=800;
  639.   eject_r=0.1;
  640.   dt=0.015;
  641.   eject_vy=4;
  642.   eject_vl=1;
  643.   shadows=1;
  644.   ridtri=0.1;
  645.  
  646.   maxage=1.0/dt;
  647.  
  648.   if(ac==2)
  649.     np=atoi(av[1]);
  650.  
  651.   if(ac==4) {
  652.     WIDTH=atoi(av[2]);
  653.     HEIGHT=atoi(av[3]);
  654.   }
  655.  
  656.   glutInitWindowPosition(0,0);
  657.   glutInitWindowSize(WIDTH,HEIGHT);
  658.   glutInit(&ac,av);
  659.  
  660.   glutInitDisplayMode(GLUT_RGB|GLUT_DEPTH|GLUT_DOUBLE);
  661.  
  662.   if(!(win=glutCreateWindow("Fire"))) {
  663.     fprintf(stderr,"Error opening a window.\n");
  664.     exit(-1);
  665.   }
  666.   
  667.   reshape(WIDTH,HEIGHT);
  668.  
  669.   inittextures();
  670.  
  671.   glShadeModel(GL_FLAT);
  672.   glEnable(GL_DEPTH_TEST);
  673.  
  674.   glEnable(GL_BLEND);
  675.   glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
  676.  
  677.   glEnable(GL_FOG);
  678.   glFogi(GL_FOG_MODE,GL_EXP);
  679.   glFogfv(GL_FOG_COLOR,fogcolor);
  680.   glFogf(GL_FOG_DENSITY,0.1);
  681. #ifdef FX
  682.   glHint(GL_FOG_HINT,GL_NICEST);
  683. #endif
  684.  
  685.   p=malloc(sizeof(part)*np);
  686.  
  687.   for(i=0;i<np;i++)
  688.     setnewpart(&p[i]);
  689.  
  690.   inittree();
  691.  
  692.   glutKeyboardFunc(key);
  693.   glutSpecialFunc(special);
  694.   glutDisplayFunc(drawfire);
  695.   glutIdleFunc(drawfire);
  696.   glutReshapeFunc(reshape);
  697.   glutMainLoop();
  698.  
  699.   return(0);
  700. }
  701.